package co.edu.poli.ficb.agl.automatable.modelo.automatas;

import java.util.Arrays;
import java.util.TreeSet;

import co.edu.poli.ficb.agl.automatable.modelo.Alfabeto;
import co.edu.poli.ficb.agl.automatable.modelo.Simbolo;
import co.edu.poli.ficb.agl.automatable.modelo.SimboloImpl;

public final class AutomataUtil {
	
	public static AutomataFinitoImpl getAutomataFigura32() {
		AutomataFinitoImpl automata = new AutomataFinitoImpl();
		
		Estado q000 = new EstadoImpl("q000");
		Estado q001 = new EstadoImpl("q001");
		Estado q010 = new EstadoImpl("q010");
		Estado q011 = new EstadoImpl("q011");
		Estado q100 = new EstadoImpl("q100");
		Estado q101 = new EstadoImpl("q101");
		Estado q110 = new EstadoImpl("q110");
		Estado q111 = new EstadoImpl("q111");
		
		Simbolo cero = new SimboloImpl('0'), uno = new SimboloImpl('1');
		
		automata.setAlfabeto(new Alfabeto(Arrays.asList(cero, uno)));
		
		automata.setEstados(new TreeSet<Estado>(Arrays.asList(q000, q001, q010, q011, q100, q101, q110, q111)));
		
		FuncionDeTransicion func = automata.getFuncionDeTransicion();
		
		func.agregarTransicion(q000, cero, q000);
		func.agregarTransicion(q000, uno, q001);
		
		func.agregarTransicion(q100, cero, q000);
		func.agregarTransicion(q100, uno, q001);
		
		func.agregarTransicion(q010, cero, q100);
		func.agregarTransicion(q010, uno, q101);
		
		func.agregarTransicion(q110, cero, q100);
		func.agregarTransicion(q110, uno, q101);
		
		func.agregarTransicion(q001, cero, q010);
		func.agregarTransicion(q001, uno, q011);
		
		func.agregarTransicion(q101, cero, q010);
		func.agregarTransicion(q101, uno, q011);
		
		func.agregarTransicion(q011, cero, q110);
		func.agregarTransicion(q011, uno, q111);
		
		func.agregarTransicion(q111, cero, q110);
		func.agregarTransicion(q111, uno, q111);
		
		return automata;
		
	}
	
	public static AutomataFinito getAutomataParCeros() {
		AutomataFinitoImpl automata = new AutomataFinitoImpl();
		final Estado s1 = new EstadoImpl("S1"), s2 = new EstadoImpl("S2");
		final Simbolo cero = new SimboloImpl('0'), uno = new SimboloImpl('1');
		automata.setAlfabeto(new Alfabeto(Arrays.asList(cero, uno)));
		automata.getEstados().add(s1);
		automata.getEstados().add(s2);
		automata.setEstadoInicial(s1);
		automata.getEstadosAceptacion().add(s1);
		automata.getFuncionDeTransicion().agregarTransicion(s1, uno, s1);
		automata.getFuncionDeTransicion().agregarTransicion(s2, uno, s2);
		automata.getFuncionDeTransicion().agregarTransicion(s1, cero, s2);
		automata.getFuncionDeTransicion().agregarTransicion(s2, cero, s1);
		return automata;
	}
	
	public static AutomataFinitoImpl getAutomataMultiplo2() {
		AutomataFinitoImpl mul2 = new AutomataFinitoImpl();
		final EstadoImpl par = new EstadoImpl("par"), impar = new EstadoImpl("impar");
		final SimboloImpl a = new SimboloImpl('a');
		mul2.setAlfabeto(new Alfabeto(new TreeSet<Simbolo>(Arrays.asList(a))));
		mul2.getEstados().add(par);
		mul2.getEstados().add(impar);
		mul2.getEstadosAceptacion().add(par);
		mul2.setEstadoInicial(par);
		mul2.getFuncionDeTransicion().agregarTransicion(par, a, impar);
		mul2.getFuncionDeTransicion().agregarTransicion(impar, a, par);
		return mul2;
	}
	
	public static AutomataFinitoImpl getAutomataMultiplo3() {
		AutomataFinitoImpl mul3 = new AutomataFinitoImpl();
		final EstadoImpl cero = new EstadoImpl("0"), uno = new EstadoImpl("1"), dos = new EstadoImpl("2");
		final SimboloImpl a = new SimboloImpl('a');
		mul3.setAlfabeto(new Alfabeto(new TreeSet<Simbolo>(Arrays.asList(a))));
		mul3.getEstados().add(cero);
		mul3.getEstados().add(uno);
		mul3.getEstados().add(dos);
		mul3.getEstadosAceptacion().add(cero);
		mul3.setEstadoInicial(cero);
		mul3.getFuncionDeTransicion().agregarTransicion(cero, a, uno);
		mul3.getFuncionDeTransicion().agregarTransicion(uno, a, dos);
		mul3.getFuncionDeTransicion().agregarTransicion(dos, a, cero);
		return mul3;
	}

	public static AutomataFinitoImpl getAutomataUnionMultiplo23() {
		//return (AutomataFinitoDeterministaBasico) AutomatasImpl.getInstance().union(getAutomataMultiplo2(), getAutomataMultiplo3());
		return (AutomataFinitoImpl) AutomatasImpl.getInstance().union((Automata)getAutomataMultiplo2(), (Automata)getAutomataMultiplo3());
	} 

	public static AutomataFinitoImpl getAutomataInterseccionMultiplo23() {
		return (AutomataFinitoImpl) AutomatasImpl.getInstance().interseccion(getAutomataMultiplo2(), getAutomataMultiplo3());
	}
	
	public static void main(String[] args) {
		Automata m1 = getAutomataMultiplo2();
		System.out.println(m1);
		
		Automata m2 = getAutomataMultiplo3();
		System.out.println(m2);
		
		Automata m = getAutomataUnionMultiplo23();
		System.out.println(m);
	}

}
